﻿using System;
using System.Globalization;
using System.Text;
using System.Collections.Generic;
using System.Linq;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using ProjectBase.Core;
using ProjectBase.Core.Service;
using ProjectBase.Core.Tools.Convert;
using ProjectBase.Data.NH;
using ProjectBase.Tools.Converter;

using $prjsn$.Common.Data.Services;
using $prjsn$.Data;
using $prjsn$.Data.Services;
using $prjsn$.Entity.Services;
using $prjsn$.Tools.IoC;

namespace $safeprojectname$.Core.Factory
{
    [TestClass]
    public class FactoryTest : TestBase
    {
        [TestMethod]
        public void GetImplementationOfInterface_Passed()
        {
            var instance = ProjectBase.Core.Service.Factory.CreateInstance<IUserDao>();
            Assert.IsTrue(instance.Is());

            Assert.IsTrue(instance is Data.Services.Xml.UserDao
                       || instance is Data.Services.UserDao);
        }

        [TestMethod]
        public void CheckTypesHierarchy_Passed()
        {
            Type baseType = typeof(BaseDao<Lang, int, LangFilter>);
            Type statType = typeof(LangDao);
            Type istatType = typeof(ILangDao);
            Type readType = typeof(IReadDao<Lang, int>);

            var isBase = statType.IsSubclassOf(baseType);
            var isEqual = statType.Equals(statType);
            var isILanguage = statType.GetInterface(istatType.Name).Is();
            var isRead = statType.GetInterfaces().Any(i => i.Equals(readType));

            Assert.IsTrue(isBase && isEqual && isILanguage && isRead);
        }
        [TestMethod]
        public void GetLangDao_Interface_Passed()
        {
            // interface
            object instance = ProjectBase.Core.Service.Factory.CreateInstance<ILangDao>();
            Assert.IsTrue(instance.Is());

            Assert.IsTrue(instance is Data.Services.Xml.LangDao
                       || instance is Data.Services.LangDao);
        }
        [TestMethod]
        public void GetLangDao_ConcreteType_Passed()
        {
            // concrete type
            object instance = ProjectBase.Core.Service.Factory.CreateInstance<Data.Services.Xml.LangDao>();

            Assert.IsTrue(instance.Is());
        }
        [TestMethod]
        public void GetLangDao_Covariance_Passed()
        {
            // covariance
            object instance = ProjectBase.Core.Service.Factory.CreateInstance<IReadDao<Lang, int, LangFilter>>();

            Assert.IsTrue(instance.Is());

            Assert.IsTrue(instance is Data.Services.Xml.LangDao
                       || instance is Data.Services.LangDao);
        }
        [TestMethod]
        public void GetLangDao_Covariance2_Passed()
        {
            // covariance
            object instance = ProjectBase.Core.Service.Factory.CreateInstance<IReadDao<Lang, int>>();

            Assert.IsTrue(instance is Data.Services.Xml.LangDao
                || instance is Data.Services.LangDao);
        }
        [TestMethod]
        public void GetInstance_ByPassingConcreteType_Passed()
        {
            var instance = ProjectBase.Core.Service.Factory.CreateInstance<INumberToWordConverter>();

            Assert.IsTrue(instance.Is());
            Assert.IsTrue(instance is NumberToWordConverter);

            instance = ProjectBase.Core.Service.Factory.CreateInstance<INumberToWordConverter>(implementor: typeof(NumberToWordConverterCs));

            Assert.IsTrue(instance.Is());
            Assert.IsTrue(instance is NumberToWordConverterCs);

            instance = ProjectBase.Core.Service.Factory.CreateInstance<INumberToWordConverter>(implementor: typeof(NumberToWordConverterEn));

            Assert.IsTrue(instance.Is());
            Assert.IsTrue(instance is NumberToWordConverterEn);
        }
        [TestMethod]
        public void GetInstances_MultipleResults_Passed()
        {
            var instances = ProjectBase.Core.Service.Factory.CreateInstances<INumberToWordConverter>();

            Assert.IsTrue(instances.IsNotEmpty());
            Assert.IsTrue(instances.Count() > 1);
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        [TestInitialize]
        public override void MyTestInitialize()
        {
            base.MyTestInitialize(); // Use TestInitialize to run code before running each test
        }

        [TestCleanup]
        public override void MyTestCleanup()
        {
            base.MyTestCleanup(); // Use TestCleanup to run code after each test has run
        }
        #endregion
    }
}
